#include<stdio.h>
#include<stdlib.h>
#include<string.h>

#define WordLenth 20
#define SentenceLenth 100

typedef struct WORD {
    char str[WordLenth];
    int TypeCode;
}Word;
Word sentence[SentenceLenth];
Word WordStack[3*SentenceLenth];
int sym = 0, tt = 0;

void MyStrrev(char cc[]) {
    int len = strlen(cc);
    for(int i = 0, j = len-1; i < j; i++, j--) {
        char temp;
        temp = cc[j];
        cc[j] = cc[i];
        cc[i] = temp;
    }
}
void MyItoa(int x, char cc[]) {
    int idx = 0;
    while(x) {
        cc[idx++] = x%10 + '0';
        x /= 10;
    }
    cc[idx++] = '\0';
    MyStrrev(cc);
}



int Tnumer = 0;
void MakeTname(Word* T) {
    char Tn[WordLenth];
    T->str[0] = 'T';
    T->str[1] = '\0';
    MyItoa(++Tnumer, Tn);
    strcat(T->str, Tn);
}

void emit(Word op, Word a, Word b, Word T) {
    if(!strcmp(op.str, ":=")) {
        printf("%s:=%s     (:=,%s,-,%s)\n", T.str, a.str, a.str, T.str);
        return;
    }
    printf("%s:=%s%s%s     (%s,%s,%s,%s)\n", T.str, a.str, op.str, b.str, op.str, a.str, b.str, T.str);
}

void SetWord(Word* t, const char cc[], int type) {
    strcpy(t->str, cc);
    t->TypeCode = type;
}

bool IsOperator(Word t) {
    if(!strcmp(t.str, ":=") || !strcmp(t.str, "-") || !strcmp(t.str, "+") \
    || !strcmp(t.str, "*") || !strcmp(t.str, "/")) {
        return 1;
    }
    return 0;
}

int ReportNum = 0;
void ReportError(const char from[], const char reason[]) {
    printf("ERROR%d FROM %s.     The reason for this error: %s.\n\n", ++ReportNum, from, reason);
    return;
}

bool A();
bool V();
bool E(Word op);
bool F(Word op);
bool T(Word op);
bool Ep();
bool Tp();

bool A() {
    if(V()) {
        ReportError("V", "this word isn't a variable name");
        return 1;
    }
    Word op;
    op = sentence[sym];
    if(strcmp(sentence[sym++].str, ":=")) {
        ReportError("A", "op is not \":=\"");
        return 1;
    }
    //WordStack[++tt] = op;
    if(E(op)) {
        ReportError("E", "This expression cannot be replaced with a variable name");
        return 1;
    }

    return 0;
}

bool E(Word op) {
    Word ph;
    SetWord(&ph, "nothing", 0);
    if(T(ph)){
        ReportError("T", "An error occurred in multiplcation and division expressions");
        return 1;
    }
    if(Ep()) {
        ReportError("Ep", "An error occurred in addation and subtraction expressions");
        return 1;
    }
    if(IsOperator(op)) {
        Word t, a, b, pw;
        //MakeTname(&t);
        b = WordStack[tt--];
        a = WordStack[tt--];
        emit(op, b, pw, a);
        WordStack[++tt] = t;    
    }
    return 0;
}

bool Ep() {
    if(!strcmp(sentence[sym].str, "+") || !strcmp(sentence[sym].str, "-")) {
        Word op = sentence[sym++];
        //WordStack[++tt] = op;
        if(T(op)) {
            ReportError("T", "Variable error occurred after operator '+'or'-'");
            return 1;
        }
        if(Ep()) {
            ReportError("Ep", "An error occurred in Rear parallel expreission");
            return 1;
        }
    }
    
    return 0;
}

bool T(Word op) {
    Word ph;
    SetWord(&ph, "nothing", 0);
    if(F(ph)) {
        ReportError("F", "This expression cannot to be converted to a correct variable");
        return 1;
    }
    if(Tp()) {
        ReportError("Tp", "An error occurred in multiplication and division expressions");
        return 1;
    }
    if(IsOperator(op)) {
        Word t, a, b;
        MakeTname(&t);
        b = WordStack[tt--];
        a = WordStack[tt--];
        emit(op, a, b, t);
        WordStack[++tt] = t;     
    }

    return 0;
}

bool Tp() {
    if(!strcmp(sentence[sym].str, "*") || !strcmp(sentence[sym].str, "/")) {
        Word op = sentence[sym++];
        //WordStack[++tt] = op;
        if(F(op)) {
            ReportError("F", "Variable error occurred after operator '*'or'/'");
            return 1;
        }
        if(Tp()) {
            ReportError("Ep", "An error occurred in Rear parallel expreission");
            return 1;
        }
    }
    return 0;
}

bool F(Word op) {
    if(!strcmp(sentence[sym].str, "(")) {
        sym++;
        Word ph;
        SetWord(&ph, "nothing", 0);
        if(E(ph)) {
            ReportError("E", "Missing variable");
            return 1;
        }
        if(strcmp(sentence[sym].str, ")")) {
            ReportError("F", "Missing operator ')'");
            return 1;
        }
        sym++;
    }
    else if(V()){
        ReportError("V", "Missing variable or this word isn't a variable name");
        return 1;
    }

    if(IsOperator(op)) {
        Word t, a, b;
        MakeTname(&t);
        b = WordStack[tt--];
        a = WordStack[tt--];
        emit(op, a, b, t);
        WordStack[++tt] = t;    
    }

    return 0; 
}

bool V() {
    Word t = sentence[sym++];
    if(t.TypeCode == 2 || t.TypeCode == 1) {
        WordStack[++tt] = t;
        return 0;
    }
    return 1;
}

int main() {
    SetWord(&sentence[0], "x", 2);
    SetWord(&sentence[1], ":=", 3);
    SetWord(&sentence[2], "a", 2);
    SetWord(&sentence[3], "+", 3);
    SetWord(&sentence[4], "b", 2);
    SetWord(&sentence[5], "*", 3);
    SetWord(&sentence[6], "c", 2);
    SetWord(&sentence[7], "/", 3);
    SetWord(&sentence[8], "d", 2);
    SetWord(&sentence[9], "-", 3);
    SetWord(&sentence[10], "(", 3);
    SetWord(&sentence[11], "e", 2);
    SetWord(&sentence[12], "+", 3);
    SetWord(&sentence[13], "f", 2);
    SetWord(&sentence[14], ")", 3);
    A();
     system("pause");
    return 0;
}

